import 'package:base_plugin/base_plugin.dart';
import 'package:dio/dio.dart';
import 'package:finance_app/src/entities/bill_detail_entity.dart';
import 'package:finance_app/src/entities/bill_entity.dart';
import 'package:finance_app/src/entities/credit_note_detail_entity.dart';
import 'package:finance_app/src/entities/credit_note_entity.dart';
import 'package:finance_app/src/entities/debit_note_detail_entity.dart';
import 'package:finance_app/src/entities/expense_detail_entity.dart';
import 'package:finance_app/src/entities/invoice_detail_entity.dart';
import 'package:finance_app/src/entities/invoice_entity.dart';
import 'package:finance_app/src/entities/payment_detail_entity.dart';
import 'package:finance_app/src/entities/payment_entity.dart';
import 'package:finance_app/src/entities/purchase_order_detail_entity.dart';
import 'package:finance_app/src/entities/purchase_order_entity.dart';
import 'package:finance_app/src/entities/quotation_detail_entity.dart';
import 'package:finance_app/src/entities/quotation_entity.dart';
import 'package:finance_app/src/entities/transaction_entity.dart';
import 'package:finance_app/src/http_service/http_transaction_service.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/date_time_utils.dart';

mixin TransactionDataMixin<T> on BaseProvider<T> {
  List<TransactionEntity> transactionList;

  Map<String, List<TransactionEntity>> transactionMap = {};

  String get currentSelectTime;

  DateTime get currentStartDate;

  DateTime get currentEndDate;

  String dueDate;

  @override
  void initState() {
    super.initState();
    loadTransaction();
  }

  String searchDataText;

  void searchRefreshData(data) async {
    if (searchDataText != data) {
      if (searchDataText == null && data == '') return;
      searchDataText = data;
      transactionList = null;
      transactionMap.clear();
      update();
      await loadTransaction();
      update();
    }
  }

  int get page => 1;

  int get rows => 15;

  bool hasUp = false;

  int _contactId;

  int get contactId => _contactId;

  set contactId(int value) {
    this._contactId = value;
  }

  String get startTime;

  String get endTime;

  int get isOverdue => null;

  Future get refreshFuture => HttpTransactionService.getTransaction(
      page: page,
      type: types,
      start_date: startTime,
      end_date: endTime,
      keyword: searchDataText,
      contactId: contactId,
      status: statusList,
      is_overdue: isOverdue);

  List<String> get types;

  List<String> get statusList => null;

  Future<void> loadTransaction() async {
    await post(refreshFuture, autoHandler: AutoHandler.Toast,
        onSuccess: (result) {
      if (transactionList == null) {
        transactionList = [];
      }
      transactionList.addAll(getFromRequestResult(result, true));
      if (transactionList.length >= rows) {
        hasUp = true;
      }
      update();
    }, onFinally: () {
      if (transactionList == null) {
        transactionList = [];
      }
      update();
    });
  }

  List<TransactionEntity> getFromRequestResult(
      Response<dynamic> result, bool isRefresh) {
    final transactionList =
        getEntityFromResult<List<TransactionEntity>>(result);
    // transactionList.sort((b, a) {
    //   return ListToMapUtils.sortIssuesAt<TransactionEntity>(
    //       a, b, (t) => t.issuedAt, (t) => t.id);
    // });
    formatMap(transactionList, isRefresh);
    return transactionList;
  }

  void formatMap(List<TransactionEntity> data, bool isRefresh) {
    if (isRefresh == true) {
      transactionMap.clear();
    }
    for (final item in data) {
      if (handleFilter(item)) {
        DateTime time = DateTimeUtils.toDateTime(item.issuedAt, 'yyyy-MM-dd');
        String month = DateTimeUtils.formatDateTime(time, 'MMM');
        if (transactionMap.containsKey(month)) {
          transactionMap[month].add(item);
        } else {
          transactionMap[month] = [item];
        }
      }
    }
  }

  bool handleFilter(TransactionEntity entity) {
    if (dueDate != null && entity.dueAt != null) {
      return DateTime.tryParse(entity.dueAt)
          .isAtSameMomentAs(DateTime.parse(dueDate));
    }
    return true;
  }

  TransactionEntity currentTapDetail;

  void onBackTransactionDetail() {}

  void onNavTransactionDetail(TransactionEntity value) async {
    currentTapDetail = value;
    print('debug: transaction:${value.transactionType}');
    var result;
    if (value.transactionType == 'expense') {
      result =
          await Routes.navigateTo(RouterGenProviders.newExpensePage, params: {
        'data': value,
        'isSelectMode': true,
      });
    } else if (value.transactionType == 'bill') {
      result = await Routes.navigateTo(RouterGenProviders.newBillPage, params: {
        'data': value,
        'isSelectMode': true,
      });
    } else if (value.transactionType == 'purchase_order') {
      result = await Routes.navigateTo(RouterGenProviders.newPurchaseOrderPage,
          params: {
            'data': value,
            'isSelectMode': true,
          });
    } else if (value.transactionType == 'cash_out') {
      result =
          await Routes.navigateTo(RouterGenProviders.newCashOutPage, params: {
        'data': value,
        'isSelectMode': true,
      });
    } else if (value.transactionType == 'cash_in') {
      result =
          await Routes.navigateTo(RouterGenProviders.newCashInPage, params: {
        'data': value,
        'isSelectMode': true,
      });
    } else if (value.transactionType == 'invoice') {
      result =
          await Routes.navigateTo(RouterGenProviders.newInvoicePage, params: {
        'data': value,
        'isSelectMode': true,
      });
    } else if (value.transactionType == 'quotation') {
      result =
          await Routes.navigateTo(RouterGenProviders.newQuotationPage, params: {
        'data': value,
        'isSelectMode': true,
      });
    } else if (value.transactionType == 'credit_note') {
      result = await Routes.navigateTo(RouterGenProviders.newCreditNotePage,
          params: {
            'data': value,
            'isSelectMode': true,
          });
    } else if (value.transactionableType == 'debit_note') {
      result =
          await Routes.navigateTo(RouterGenProviders.newDebitNotePage, params: {
        'data': value,
        'isSelectMode': true,
      });
    }
    onBackTransactionDetail();
    // print('订单返回内容:$result');
    if (result != null) {
      if (result is Map && result['delete'] != null) {
        transactionList.remove(value);
        // print('删除订单');
        onTransactionDeleted();
        formatMap(transactionList, true);
        update();
        currentTapDetail = null;
      } else {
        updateTapDetailItem(result);
        currentTapDetail = null;
      }
    }
  }

  void onTransactionDeleted() {}

  void updateTapDetailItem(dynamic result) {
    if (currentTapDetail == null) return;
    if (result is ExpenseDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is QuotationEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is QuotationDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.isOverdue = result.isOverdue;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is PurchaseOrderDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is PurchaseOrderEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is InvoiceEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.isOverdue = result.isOverdue;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is InvoiceDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.isOverdue = result.isOverdue;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is BillEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.isOverdue = result.isOverdue;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is BillDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.isOverdue = result.isOverdue;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is PaymentEntity) {
      currentTapDetail.total = result.total;
      // currentTapDetail.status = result.status;
      currentTapDetail.name = result.name;
      currentTapDetail.issuedAt = result.issuedAt;
      // currentTapDetail.number = result.number;
    } else if (result is PaymentDetailEntity) {
      currentTapDetail.total = result.total;
      // currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact?.name ?? result?.name;
      currentTapDetail.issuedAt = result.issuedAt;
      // currentTapDetail.number = result.number;
    } else if (result is CreditNoteEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is CreditNoteDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.currencyCode = result.currencyCode;
    } else if (result is DebitNoteDetailEntity) {
      currentTapDetail.total = result.total;
      currentTapDetail.status = result.status;
      currentTapDetail.name = result.contact.name;
      currentTapDetail.issuedAt = result.issuedAt;
      currentTapDetail.number = result.number;
      currentTapDetail.currencyCode = result.currencyCode;
    }
    update();
  }
}
